package main

import (
	"context"
	"flag"
	"fmt"
	"io"
	"os"

	log "github.com/sirupsen/logrus"
	glog "gitlab.com/gitlab-org/gitaly/v14/internal/log"
)

const usage = `Usage: gitaly-tools SUBCOMMAND ARGS

Subcommands:

archive [options]
	管理已合并MR的引用归档操作，通过调用GitLab API获取已合并的MR列表，
	并将相应的refs/merge-requests/<mr-iid>/head引用添加到归档等待列表中。

	Options:
	  -config=PATH        Gitaly配置文件路径 (必需)
	  -project-id=ID      GitLab项目ID (必需)
	  -repository-path=PATH 仓库路径 (必需)
	  -storage-name=NAME  Gitaly存储名称 (如果不指定则使用配置中的第一个存储)
	  -gitlab-token=TOKEN GitLab API访问令牌 (必需)
	  -gitlab-url=URL     GitLab实例URL (默认: https://gitlab.com)
	  -merged-after=DATE  获取指定日期后合并的MR (格式: 2006-01-02T15:04:05Z)
	  -dry-run           仅显示将要处理的引用，不执行实际操作
	  -creator-id=ID     操作创建者ID (默认: 0)
	  -creator-name=NAME 操作创建者名称 (默认: "gitaly-tools")
	  -reason=REASON     归档操作的原因说明 (默认: "Auto archive merged MRs")

archive-keeparound [options]
	将当前仓库中所有的keep-around引用添加到归档等待列表中，
	实现批量自动归档keep-around引用。

	Options:
	  -config=PATH        Gitaly配置文件路径 (必需)
	  -repository-path=PATH 仓库路径 (必需)
	  -storage-name=NAME  Gitaly存储名称 (如果不指定则使用配置中的第一个存储)
	  -dry-run           仅显示将要处理的引用，不执行实际操作
	  -creator-id=ID     操作创建者ID (默认: 0)
	  -creator-name=NAME 操作创建者名称 (默认: "gitaly-tools")
	  -reason=REASON     归档操作的原因说明 (默认: "Batch archive keep-around refs")
`

type subcmd interface {
	Flags(*flag.FlagSet)
	Run(ctx context.Context, stdin io.Reader, stdout io.Writer) error
}

var subcommands = map[string]subcmd{
	"archive":           &archiveSubcommand{},
	"archive-keeparound": &archiveKeepAroundSubcommand{},
}

func main() {
	glog.Configure(glog.Loggers, "", "")

	if len(os.Args) < 2 {
		fatal(usage)
	}

	subcmdName := os.Args[1]
	subcmd, ok := subcommands[subcmdName]
	if !ok {
		fatal(fmt.Sprintf("unknown subcommand: %q\n\n%s", subcmdName, usage))
	}

	flags := flag.NewFlagSet(subcmdName, flag.ExitOnError)
	subcmd.Flags(flags)
	_ = flags.Parse(os.Args[2:])

	if err := subcmd.Run(context.Background(), os.Stdin, os.Stdout); err != nil {
		log.Fatalf("执行%s命令失败: %v", subcmdName, err)
	}
}

func fatal(msg string) {
	fmt.Fprintln(os.Stderr, msg)
	os.Exit(1)
}
